1   /*
2    * Copyright (c) 2004-2005, University Health Network.  All rights reserved. Distributed under the BSD 
3    * license (see http://opensource.org/licenses/bsd-license.php).
4    *  
5    * Created on 10-Jan-2005
6    */
7   package ca.uhn.cache.internal.impl;
8   
9   import java.util.Date;
10  
11  import org.jmock.Mock;
12  import org.jmock.MockObjectTestCase;
13  import org.jmock.core.Constraint;
14  import ca.uhn.cache.CacheReasonEnum;
15  import ca.uhn.cache.IQuery;
16  import ca.uhn.cache.IQueryResult;
17  import ca.uhn.cache.VolatilityEnum;
18  import ca.uhn.cache.impl.Chunk;
19  import ca.uhn.cache.impl.Dimension;
20  import ca.uhn.cache.impl.Query;
21  import ca.uhn.cache.impl.StringParam;
22  import ca.uhn.cache.internal.ICacheCleaner;
23  import ca.uhn.cache.internal.IChunk;
24  import ca.uhn.cache.internal.IChunkIterator;
25  import ca.uhn.cache.internal.IChunkPurger;
26  import ca.uhn.cache.internal.IChunkStore;
27  import ca.uhn.cache.internal.IQueryResultStore;
28  import ca.uhn.cache.internal.exception.QueryResultStoreException;
29  
30  /***
31   * Unit tests for CacheCleaner. 
32   * 
33   * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
34   * @version $Revision: 1.1 $ updated on $Date: 2005/01/24 22:52:21 $ by $Author: bryan_tripp $
35   */
36  public class CacheCleanerTest extends MockObjectTestCase {
37  
38      private Mock myChunkStoreMock;
39      private IChunkStore myChunkStore;
40      private Mock myPurgerMock;
41      private IChunkPurger myPurger;
42      private MockResultStore myResultStore;
43      
44      /*
45       * @see TestCase#setUp()
46       */
47      protected void setUp() throws Exception {
48          myChunkStoreMock = mock( IChunkStore.class );
49          myChunkStore = (IChunkStore) myChunkStoreMock.proxy();
50  
51          myPurgerMock = mock( IChunkPurger.class );
52          myPurger = (IChunkPurger) myPurgerMock.proxy();
53          
54          //Mock myResultStoreMock = mock( IQueryResultStore.class );
55          //IQueryResultStore myResultStore = (IQueryResultStore) myResultStoreMock.proxy();
56          myResultStore = new MockResultStore();
57      }
58  
59      /***
60       * Constructor for CacheCleanerTest.
61       * @param theName ... 
62       */
63      public CacheCleanerTest(String theName) {
64          super(theName);
65      }
66  
67      /***
68       */
69      public void testEvictStaleChunks() {
70          ICacheCleaner cleaner = new CacheCleaner(myChunkStore, myPurger, 10, myResultStore, .1f);
71          
72          ChunkIterator staleChunks = new ChunkIterator();
73          Date now = new Date();
74          Query dummyQuery = new Query();
75          dummyQuery.addParameter(new StringParam(new Dimension("dim1", new Class[] {StringParam.class}), "foo"));
76          
77          IChunk stale1 = new Chunk("one", VolatilityEnum.STABLE, now, now, now, new CacheReasonEnum[0], dummyQuery);
78          IChunk stale2 = new Chunk("two", VolatilityEnum.STABLE, now, now, now, new CacheReasonEnum[0], dummyQuery);
79          staleChunks.add(stale1);
80          staleChunks.add(stale2);
81          staleChunks.finished();
82          myPurgerMock.expects( once() ).method("getStaleChunks").will(returnValue(staleChunks));
83          myChunkStoreMock.expects( once() ).method("remove").with(new Constraint[] {eq(stale1.getBoundaries())});
84          myChunkStoreMock.expects( once() ).method("remove").with(new Constraint[] {eq(stale2.getBoundaries())});
85  
86          //this fails with a NullPointerException in the proxy, and I can't see why, so I'm coding 
87          //a custom mock object instead 
88          //resultStoreMock.expects( atLeastOnce() ).method("delete");  
89  
90          cleaner.evictStaleChunks();
91          
92          assertEquals(2, myResultStore.getDeleteCalls());
93      }
94  
95      /***
96       */
97      public void testEvictUnusedChunks() {
98          ICacheCleaner cleaner = new CacheCleaner(myChunkStore, myPurger, 10, myResultStore, .1f);
99  
100         myPurgerMock.expects( once() ).method("getLowestVogueness")
101             .will(returnValue(System.currentTimeMillis() - 1000 * 120));
102         myPurgerMock.expects( atLeastOnce() ).method("getNumCachedItems")
103             .will(onConsecutiveCalls(returnValue(20), returnValue(15), returnValue(10)));
104         myPurgerMock.expects( atLeastOnce() ).method("getUnusedChunks")
105             .will(onConsecutiveCalls(returnValue(getDummyIterator(1)), returnValue(getDummyIterator(1))));
106         
107         myChunkStoreMock.expects( atLeastOnce() ).method("remove");
108         
109         cleaner.evictUnusedChunks();
110         
111         assertEquals(2, myResultStore.getDeleteCalls());
112     }
113     
114     private IChunkIterator getDummyIterator(int theNumChunks) {
115         ChunkIterator result = new ChunkIterator();
116         
117         Date now = new Date();
118         Query dummyQuery = new Query();
119         dummyQuery.addParameter(new StringParam(new Dimension("1", new Class[] {StringParam.class}), "a"));
120         
121         for (int i = 0; i < theNumChunks; i++) {
122             IChunk x = new Chunk("x", VolatilityEnum.STABLE, now, now, now, new CacheReasonEnum[0], dummyQuery); 
123             result.add(x);
124         }
125         result.finished();
126         
127         return result;
128     }
129     
130     /***
131      * Because I can't get the jmock version working. 
132      * 
133      * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
134      * @version $Revision: 1.1 $ updated on $Date: 2005/01/24 22:52:21 $ by $Author: bryan_tripp $
135      */
136     private class MockResultStore implements IQueryResultStore {
137         
138         private int myDeleteCalls;
139         
140         /*** 
141          * @see ca.uhn.cache.internal.IQueryResultStore#insert(ca.uhn.cache.IQueryResult)
142          */
143         public void insert(IQueryResult theQueryResult) throws QueryResultStoreException {
144         }
145 
146         /*** 
147          * @see ca.uhn.cache.internal.IQueryResultStore#select(ca.uhn.cache.IQuery)
148          */
149         public IQueryResult select(IQuery theQuery) throws QueryResultStoreException {
150             return null;
151         }
152 
153         /***
154          * @see ca.uhn.cache.internal.IQueryResultStore#delete(ca.uhn.cache.IQuery)
155          */
156         public int delete(IQuery theProjection) throws QueryResultStoreException {
157             myDeleteCalls++;
158             return 0;
159         }
160         
161         /***
162          * @return number of times delete was called
163          */
164         public int getDeleteCalls() {
165             return myDeleteCalls;
166         }
167         
168     }
169 
170 }